#include "guiterm.hpp"
#include <qtimer.h>
#include "config.h"

static void handleArgs(int argc, char **argv);
static void printHelpText();
static void printVersion();
static void argumentError(const char *fmt, ...);

const char *commandName = "guiterm";

Frontend *frontend;

int main(int argc, char **argv)
{
	setAlwaysTrace(true);
	
	frontend = new Frontend();
	int ret = frontend->main(argc, argv);
	delete frontend;
	
	return ret;
}

Frontend::Frontend()
{
}

Frontend::~Frontend()
{
	//delete backend;
}

int Frontend::main(int argc, char **argv)
{
	QApplication app(argc, argv);
	
	handleArgs(argc, argv);

	connect(&app, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(focusChanged(QWidget*,QWidget*)));
	
	initConfig();
	
	TerminalWindow *window = new TerminalWindow();
	window->createTab();
	window->show();
	
	int ret = app.exec();
	
	return ret;
}

void Frontend::focusChanged(QWidget *old, QWidget *now)
{
	// When changing to NULL focus, it means that something has closed (eg,
	// menu closed, tab deleted, etc). In that case, figure out which window
	// the old widget was part of, and focus on its 'standard focus'.
	if(now == NULL && old != NULL)
	{
		QWidget *window = old->window();
		if(window && window!=old)
		{
			TerminalWindow *termWindow = dynamic_cast<TerminalWindow*>(window);
			if(termWindow)
				termWindow->giveFocus();
		}
	}
}

extern "C" {
	int run_timers(long now, long *next);
	unsigned long getticks(void);
}

void Frontend::timerChangeNotify(long next)
{
	if(scheduledTimers.find(next)==scheduledTimers.end()) {
		scheduledTimers.insert(next);
		long delay = next - getticks();
		if(delay < 0) delay = 0;
		QTimer::singleShot(delay, frontend, SLOT(puttyTimerExpired()));
	}
}

void Frontend::puttyTimerExpired()
{
	set<long>::iterator it = scheduledTimers.begin();
	long now = *it;
	scheduledTimers.erase(it);
	
	long next;
	if(run_timers(now, &next))
		timerChangeNotify(next);
}



void handleArgs(int argc, char **argv)
{
	commandName = argv[0];
	
	for(int ii=1; ii<argc; ii++)
	{
		string arg = argv[ii];
		
		if(arg == "-v" || arg == "--version") {
			printVersion();
			exit(0);
		} else if(arg == "-h" || arg == "-help" || arg == "--help") {
			printHelpText();
			exit(0);
		} else if(arg=="--trace") {
			ii++;
			if(ii >= argc)
				argumentError("--trace: option requires an argument");
			setAlwaysTrace(true);
			traceOutputName = argv[ii];
		} else if(arg[0]=='-') {
			argumentError("%s: invalid option", arg.c_str());
		} else {
			// TODO
		}
	}
}

void printHelpText()
{
	printf(
	"guiterm is a command line terminal.\n"
	"\n"
	"Usage: guiterm [option] [command]\n"
	"\n"
	" -h, --help     Display this help and exit\n"
	" -v, --version  Output version information and exit\n"
	"\n"
	"Report bugs to http://code.google.com/p/guishell/issues/entry\n"
	);
}

void printVersion()
{
	printf(
	"guiterm %s\n"
	"\n"
	"Copyright (C) 2009 Jim Babcock\n"
	"This is free software; see the source for copying conditions.  There is NO\n"
	"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
		,PACKAGE_VERSION
	);
}

void argumentError(const char *fmt, ...)
{
	va_list arglist;
	va_start(arglist, fmt);
	std::string msg = retvprintf(fmt, arglist);
	va_end(arglist);
	
	fprintf(stderr, "%s: %s\n", commandName, msg.c_str());
	exit(1);
}

